package io.kimmking.dubbo.common.distributelock;

import io.kimmking.dubbo.common.unit.ThrowableActionV2;

import java.util.concurrent.TimeUnit;

/**
 * 分布式锁接口，基于Redisson的分布式锁需要实现该接口
 */
public interface DistributedLock {

    ZLock lock(String key, long leaseTime, TimeUnit unit, boolean isFair) throws Exception;

    default ZLock lock(String key, long leaseTime, TimeUnit unit) throws Exception {
        return this.lock(key, leaseTime, unit, false);
    }

    default ZLock lock(String key, boolean isFair) throws Exception {
        return this.lock(key, -1, TimeUnit.MILLISECONDS, isFair);
    }

    default ZLock lock(String key) throws Exception {
        return this.lock(key,-1, null, false);
    }

    /**
     * 尝试获取锁
     * @param key
     * @param waitTime
     * @param leaseTime
     * @param unit
     * @param isFair
     * @return
     * @throws Exception
     */
    ZLock tryLock(String key, long waitTime, long leaseTime, TimeUnit unit, boolean isFair) throws Exception;

    default ZLock tryLock(String key, long waitTime, long leaseTime, TimeUnit unit) throws Exception{
        return this.tryLock(key, waitTime, leaseTime, unit, false);
    };

    default ZLock tryLock(String key, long waitTime, TimeUnit unit, boolean isFair) throws Exception {
        return this.tryLock(key, waitTime, -1, unit, isFair);
    }

    default ZLock tryLock(String key, long waitTime, TimeUnit unit) throws Exception {
        return this.tryLock(key, waitTime, -1, unit, false);
    }

    /**
     *  释放锁
     * @param lock 锁对象
     * @throws Exception
     */
    void unlock(Object lock) throws Exception;

    default void unlock(ZLock zLock){
        ThrowableActionV2.execute(() -> {
            if(zLock != null)
                this.unlock(zLock.getLock());
        });
    }
}